﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if !WINDOWS_PHONE


#endif

namespace DARE
{
    [AttrTypeDependentSerializable(typeof(DARE.Save.DataStructures.CSphereModelData))]
    public class CSphereModel : CBasicModel
    {

    #region fields

        private int m_slices = 20;

    #endregion

    #region properties

        public override int Slices
        {
            get { return m_slices; }
            set
            {
                if ((value != m_slices) && (m_slices >= 4))
                {
                    m_slices = value;
                    SetupVertices();
                    SetUpNormals();
                    CreateVertexBuffer();
                }
            }
        }

    #endregion

    #region ctor

        public CSphereModel(string name) : 
            base(name)
        {
            Initialize();
        }

        public CSphereModel(string name, float diameter) : 
            base(name, diameter, diameter, diameter)
        {
            Initialize();
        }

        public CSphereModel(float diameter) : 
            base(diameter, diameter, diameter)
        {
            Initialize();
        }

        private void Initialize()
        {
            //m_cullMode = CullMode.None;
            CullMode = CullMode.None;
            SetupVertices();
            SetUpNormals();
            CreateVertexBuffer();
        }

        public override AModel Clone()
        {
            CSphereModel clone = new CSphereModel(m_name, m_size.X);

            base.CopyPropertiesTo(clone);
            return clone;
        }

    #endregion

    #region setup

        protected void SetUpNormals()
        {
            for (int i = 0; i < m_vertices.Length; ++i)
            {
                m_vertices[i].Normal = m_vertices[i].Position;
                m_vertices[i].Normal.Normalize();
            }
        }

        protected void SetupVertices()
        {
            m_size /= 2.0f;

            float radius = m_size.X;
            int index = 0;
#if WINDOWS_PHONE
            m_vertices = new VertexPositionNormalTexture[(m_slices / 2) * m_slices * 6];
#else
            m_vertices = new VertexPositionNormalTextureTangentBinormal[(m_slices / 2) * m_slices * 6];
#endif
            // points definition and normal
            Vector3 bottomLeft = Vector3.Zero;
            Vector3 bottomRight = Vector3.Zero;
            Vector3 topRight = Vector3.Zero;
            Vector3 topLeft = Vector3.Zero;
            Vector3 normal = Vector3.Zero;

            // angles needed to create the vertices
            float a = 0.0f;
            float an = 0.0f;
            float b = 0.0f;
            float bn = 0.0f;

            // sphere creation
            for (int j = -m_slices / 4; j < m_slices / 4; ++j)
            {
                for (int i = 0; i < m_slices; ++i)
                {
                    // calculate the angles
                    a = ((float)j) * (MathHelper.TwoPi / m_slices);
                    an = ((float)j + 1) * (MathHelper.TwoPi / m_slices);
                    b = ((float)i) * (MathHelper.TwoPi / m_slices);
                    bn = ((float)i + 1) * (MathHelper.TwoPi / m_slices);

                    // calculate the points and the normal
                    bottomLeft = new Vector3(
                        radius * (float)Math.Cos(a) * (float)Math.Cos(b), 
                        radius * (float)Math.Cos(a) * (float)Math.Sin(b), 
                        radius * (float)Math.Sin(a));
                    bottomRight = new Vector3(
                        radius * (float)Math.Cos(an) * (float)Math.Cos(b), 
                        radius * (float)Math.Cos(an) * (float)Math.Sin(b), 
                        radius * (float)Math.Sin(an));
                    topRight = new Vector3(
                        radius * (float)Math.Cos(an) * (float)Math.Cos(bn), 
                        radius * (float)Math.Cos(an) * (float)Math.Sin(bn), 
                        radius * (float)Math.Sin(an));
                    topLeft = new Vector3(
                        radius * (float)Math.Cos(a) * (float)Math.Cos(bn), 
                        radius * (float)Math.Cos(a) * (float)Math.Sin(bn), 
                        radius * (float)Math.Sin(a));
                    normal = Vector3.Cross(topLeft - bottomLeft, bottomRight - bottomLeft);
                    normal.Normalize();
#if WINDOWS_PHONE
                    // set the vertices                    
                    if (j == m_slices / 4 - 1)
                    {
                        m_vertices[index++] = new VertexPositionNormalTexture(topRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(topLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(bottomLeft, normal, Vector2.Zero);
                    }
                    else if (j == -m_slices / 4)
                    {
                        m_vertices[index++] = new VertexPositionNormalTexture(bottomLeft, -normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(bottomRight, -normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(topRight, -normal, Vector2.Zero);
                    }
                    else
                    {
                        m_vertices[index++] = new VertexPositionNormalTexture(bottomLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(bottomRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(topRight, normal, Vector2.Zero);

                        m_vertices[index++] = new VertexPositionNormalTexture(bottomLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(topRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTexture(topLeft, normal, Vector2.Zero);
                    }
#else
                    // set the vertices                    
                    if (j == m_slices / 4 - 1)
                    {
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomLeft, normal, Vector2.Zero);
                    }
                    else if (j == -m_slices / 4)
                    {
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomLeft, -normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomRight, -normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topRight, -normal, Vector2.Zero);
                    }
                    else
                    {
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topRight, normal, Vector2.Zero);

                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(bottomLeft, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topRight, normal, Vector2.Zero);
                        m_vertices[index++] = new VertexPositionNormalTextureTangentBinormal(topLeft, normal, Vector2.Zero);
                    }
#endif
                }
            }

            m_size *= 2.0f;
        }

    #endregion

    }
}
